package br.com.caelum.vraptor.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;

import net.sf.jxls.exception.ParsePropertyException;
import net.sf.jxls.transformer.Configuration;
import net.sf.jxls.transformer.XLSTransformer;
import br.com.caelum.vraptor.Controller;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.observer.download.Download;
import br.com.caelum.vraptor.observer.download.FileDownload;
import br.urca.dao.AlunosCursoDAO;
import br.urca.dao.SolicitacaoCarteirinhaDAO;
import br.urca.interceptor.InterceptResource;
import br.urca.model.AlunoCurso;
import br.urca.model.SolicitacaoCarteirinha;
import br.urca.session.UsuarioLogado;
import br.urca.util.ESituacaoCarteirinha;
import br.urca.util.XLSCarteirinha;

@Controller
@InterceptResource
public class IndexController {
	
	List<String> fileList;
    private static final String OUTPUT_ZIP_FILE = "\\fotos.zip";
    private static String SOURCE_FOLDER = "";	
	private static final String TEMPLATE_XLS = "\\carteirinha.xls";
	private static final String NOME_ARQUIVO_SAIDA = "\\carteirinhas_pendente.xls";
	
	private UsuarioLogado usuarioLogado;
	private Result result;
	private ServletContext context;
	private HttpServletRequest httpRequest;
	private SolicitacaoCarteirinhaDAO mCarteirinhaDAO;
	private AlunosCursoDAO mAlunosCursoDAO;

	public IndexController() { }
	
	@Inject
	public IndexController(UsuarioLogado usuarioLogado, Result result,
			SolicitacaoCarteirinhaDAO mCarteirinhaDAO,
			AlunosCursoDAO mAlunosCursoDAO, ServletContext context,
			HttpServletRequest httpRequest) {
		this.result = result;
		this.usuarioLogado = usuarioLogado;
		this.context = context;
		this.httpRequest = httpRequest;
		this.mCarteirinhaDAO = mCarteirinhaDAO;
		this.mAlunosCursoDAO = mAlunosCursoDAO;
		fileList = new ArrayList<String>();
	}

	@Path("/")
	public void index() {		
		result.include("funcionario",usuarioLogado.getFuncionario());
	}
	
	@PostConstruct
	public void listarSolicitacoesPendentes() {
		List<SolicitacaoCarteirinha> listSolicitacoes = mCarteirinhaDAO.getListPorSituacao(ESituacaoCarteirinha.PENDENTE);
		List<XLSCarteirinha> mList = new ArrayList<XLSCarteirinha>();
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		if (listSolicitacoes != null && !listSolicitacoes.isEmpty()) {
			for (SolicitacaoCarteirinha sc: listSolicitacoes) {
				AlunoCurso ac = mAlunosCursoDAO.buscaPorMatricula(sc.getId().getMatricula());
				mList.add(new XLSCarteirinha(sc.getId().getMatricula(), String.valueOf(sc.getId().getVia()), 
						ac.getAluno().getNome(), (ac.getAluno().getDtNascimento() != null ? sdf.format(ac.getAluno().getDtNascimento()) : "" ),
						(ac.getAluno().getRg() != null ? ac.getAluno().getRg() : "" ),
						(ac.getAluno().getCpf() != null ? ac.getAluno().getCpf()  : "" ), 
						ac.getCurso().getNomeCurso(), sc.getId().getMatricula().concat(".jpg")));	
			}
		}
		result.include("lista_solicitacoes", mList);
	}
	
	public void confirmarImpressao(String matricula, String via) {
		if (matricula != null && via != null) {
			SolicitacaoCarteirinha sCarteirinha = mCarteirinhaDAO.getSolicitacao(matricula, Short.valueOf(via));
			if (sCarteirinha != null) {
				sCarteirinha.setDataEmissao(new Date());
				sCarteirinha.setSituacao((short)ESituacaoCarteirinha.EMITIDA.getTipo());
				mCarteirinhaDAO.salvar(sCarteirinha);
				result.include("mensagem", "Situação atualizada com sucesso!").redirectTo(this).index();
			} else {
				result.include("mensagem", "Não foi possível atualilzar o status da solicitação. Tente novamente!").redirectTo(this).index();
			}
		} else {
			result.include("mensagem", "Dados inválidos. Tente novamente!").redirectTo(this).index();
		}
	}
	
	@Get("/solicitacoes_pendentes.xls")
	public Download arquivoXLS() throws InvalidFormatException, IOException, ParsePropertyException {
		
		String pathTemplate = context.getRealPath("/WEB-INF/reports/");
		String pathArquivoTemp = context.getRealPath("/WEB-INF/temp/");					
		
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		List<SolicitacaoCarteirinha> listSolicitacoes = mCarteirinhaDAO.getListPorSituacao(ESituacaoCarteirinha.PENDENTE);
		List<XLSCarteirinha> mList = new ArrayList<XLSCarteirinha>();
		
		if (listSolicitacoes != null && !listSolicitacoes.isEmpty()) {
			for (SolicitacaoCarteirinha sc: listSolicitacoes) {
				AlunoCurso ac = mAlunosCursoDAO.buscaPorMatricula(sc.getId().getMatricula());
				mList.add(new XLSCarteirinha(sc.getId().getMatricula(), String.valueOf(sc.getId().getVia()), 
						ac.getAluno().getNome(), (ac.getAluno().getDtNascimento() != null ? sdf.format(ac.getAluno().getDtNascimento()) : "" ),
						(ac.getAluno().getRg() != null ? ac.getAluno().getRg() : "" ),
						(ac.getAluno().getCpf() != null ? ac.getAluno().getCpf()  : "" ), 
						ac.getCurso().getNomeCurso(), sc.getId().getMatricula().concat(".jpg")));	
			}
		}
		
		Map beans = new HashMap();
		beans.put("XLSCarteirinha", mList);
		Configuration config = new Configuration();
		XLSTransformer transformer = new XLSTransformer( config );
		transformer.groupCollection("XLSCarteirinha.curso");
		transformer.transformXLS(pathTemplate + TEMPLATE_XLS, beans, pathArquivoTemp +NOME_ARQUIVO_SAIDA);
		
		File file = new File(pathArquivoTemp + NOME_ARQUIVO_SAIDA);
		
		return new FileDownload(file, httpRequest.getServletContext().getMimeType(file.getName()),"solicitacoes_pendentes.xls", true);
		
	}
	
	@Get("/arquivos_fotos.zip")
	public Download zipFotos() {
		this.SOURCE_FOLDER = context.getInitParameter("pathFotos");
		String pathArquivoTemp = context.getRealPath("/WEB-INF/temp/");	
		File file = new File(pathArquivoTemp + OUTPUT_ZIP_FILE);
		if (file.exists()) {
			file.delete();
		}
		
    	generateFileList(new File(SOURCE_FOLDER));
    	zipIt(pathArquivoTemp + OUTPUT_ZIP_FILE);
    	
    	file = new File(pathArquivoTemp + OUTPUT_ZIP_FILE);
		
		try {
			return new FileDownload(file, httpRequest.getServletContext().getMimeType(file.getName()),"fotos.zip", true);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
     * @param zipFile output ZIP file location
     */
	public void zipIt(String zipFile) {
		byte[] buffer = new byte[1024];
		try {
			FileOutputStream fos = new FileOutputStream(zipFile);
			ZipOutputStream zos = new ZipOutputStream(fos);
			// System.out.println("Output to Zip : " + zipFile);
			for (String file : this.fileList) {

				System.out.println("File Added : " + file);
				ZipEntry ze = new ZipEntry(file);
				zos.putNextEntry(ze);

				FileInputStream in = new FileInputStream(SOURCE_FOLDER
						+ File.separator + file);
				int len;
				while ((len = in.read(buffer)) > 0) {
					zos.write(buffer, 0, len);
				}
				in.close();
			}
			zos.closeEntry();
			// remember close it
			zos.close();
			// System.out.println("Done");
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
 
    /**
     * Traverse a directory and get all files,
     * and add the file into fileList  
     * @param node file or directory
     */
	public void generateFileList(File node) {
		// add file only
		if (node.isFile()) {
			if (!node.getName().equalsIgnoreCase("user.png"))
				fileList.add(generateZipEntry(node.getAbsoluteFile().toString()));
		}
		if (node.isDirectory()) {
			String[] subNote = node.list();
			for (String filename : subNote) {
				generateFileList(new File(node, filename));
			}
		}
	}
 
    /**
     * Format the file path for zip
     * @param file file path
     * @return Formatted file path
     */
    private String generateZipEntry(String file){
    	return file.substring(SOURCE_FOLDER.length()+1, file.length());
    }
	
}